package com.example.admin.mybledemo;

import android.bluetooth.BluetoothGattCharacteristic;
import cn.com.heaton.blelibrary.ble.BleLog;

import com.example.admin.mybledemo.ota.BleCommunicator;
import com.example.admin.mybledemo.ota.BootDeviceScanner;
import com.example.admin.mybledemo.ota.FirmwareParser;
import com.example.admin.mybledemo.ota.OtaBlock;
import com.example.admin.mybledemo.ota.OtaConfig;
import com.example.admin.mybledemo.ota.OtaConstants;
import com.example.admin.mybledemo.ota.OtaStateMachine;
import com.example.admin.mybledemo.ota.OtaState;
import com.example.admin.mybledemo.ota.ProtocolVersion;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import cn.com.heaton.blelibrary.ble.Ble;
import cn.com.heaton.blelibrary.ble.model.BleDevice;
import cn.com.heaton.blelibrary.ble.BleLog;

/**
 * OTA升级管理器 - 协调器
 * 负责协调各个模块，管理OTA升级的整体流程和生命周期。
 */
public class OtaManager implements BleCommunicator.CommunicationCallback, OtaStateMachine.StateMachineCallback {

    private static final String TAG = "OtaManager";

    // 单例实例
    private static volatile OtaManager instance;

    // 核心组件
    private FirmwareParser firmwareParser;
    private BleCommunicator bleCommunicator;
    private OtaStateMachine otaStateMachine;
    private BootDeviceScanner bootDeviceScanner;

    // 配置和状态
    private OtaConfig config;
    private RetryState retryState;
    private OtaProgressListener progressListener;

    // 调度器用于处理延迟和超时
    private ScheduledExecutorService executorService;
    private ScheduledFuture<?> timeoutTask;

    // 升级数据
    private List<OtaBlock> otaBlocks = new ArrayList<>();
    private BleDevice targetDevice;
    private String creditCode;
    private String macAddress;

    // 前后台状态管理
    private boolean isAppInForeground = true;
    private boolean isAppRestarting = false;

    // 随机MAC地址处理
    private List<String> historicalMacAddresses = new ArrayList<>();
    private int macAddressChangeCount = 0;

    

    private ConnectionStateListener connectionStateListener;

    // 进度监听器 (从OtaManager中提取，保持兼容性)
    public interface OtaProgressListener {
        void onStateChanged(OtaState state);
        void onProgressChanged(int progress, int total);
        void onError(int errorCode, String errorMessage);
        void onSuccess();
        void onLog(String message);
        void onVersionInfo(String deviceVersion, String romVersion, String targetVersion);
        void onProtocolDetected(ProtocolVersion version);
    }

    public interface ConnectionStateListener {
        void onConnectionStateChanged(BleDevice device);
    }

    // 版本信息 (从OtaManager中提取，保持兼容性)
    public static class VersionInfo {
        public String softwareVersion;
        public String romVersion;
        public String protocolVersion;
        public boolean isCompatible;
        public String targetVersion;

        public VersionInfo(String softwareVersion, String romVersion, String protocolVersion, String targetVersion) {
            this.softwareVersion = softwareVersion;
            this.romVersion = romVersion;
            this.protocolVersion = protocolVersion;
            this.targetVersion = targetVersion;
            this.isCompatible = checkCompatibility();
        }

        private boolean checkCompatibility() {
            // 版本兼容性检查
            if (targetVersion == null || targetVersion.isEmpty()) {
                return true; // 没有目标版本要求，认为兼容
            }

            // 检查ROM版本兼容性
            if (!isRomVersionCompatible(romVersion, targetVersion)) {
                return false;
            }

            // 检查软件版本兼容性
            if (!isSoftwareVersionCompatible(softwareVersion, targetVersion)) {
                return false;
            }

            return true;
        }

        private boolean isRomVersionCompatible(String romVersion, String targetVersion) {
            // 简化的ROM版本兼容性检查
            return romVersion != null && !romVersion.isEmpty();
        }

        private boolean isSoftwareVersionCompatible(String softwareVersion, String targetVersion) {
            // 简化的软件版本兼容性检查
            return softwareVersion != null && !softwareVersion.isEmpty();
        }
    }

    // 重试状态 (从OtaManager中提取，保持兼容性)
    public static class RetryState {
        public int connectRetryCount = 0;
        public int versionCheckRetryCount = 0;
        public int credentialCheckRetryCount = 0;
        public int dataTransferRetryCount = 0;
        public int verificationRetryCount = 0;

        public void reset() {
            connectRetryCount = 0;
            versionCheckRetryCount = 0;
            credentialCheckRetryCount = 0;
            dataTransferRetryCount = 0;
            verificationRetryCount = 0;
        }
    }

    private OtaManager() {
        this.executorService = Executors.newSingleThreadScheduledExecutor();
        this.config = new OtaConfig();
        // 重要：初始化时就使用正确的配置，与Flutter端保持一致
        this.config.maxRetryCount = OtaConstants.MAX_RETRY_COUNT;
        this.config.connectTimeout = OtaConstants.CONNECT_TIMEOUT;
        this.retryState = new RetryState();
        this.firmwareParser = new FirmwareParser();
        this.bleCommunicator = new BleCommunicator(this); // Pass 'this' as CommunicationCallback
        this.otaStateMachine = new OtaStateMachine(this, bleCommunicator, firmwareParser, this.config, retryState); // Pass 'this' as StateMachineCallback
    }

    public static OtaManager getInstance() {
        if (instance == null) {
            synchronized (OtaManager.class) {
                if (instance == null) {
                    instance = new OtaManager();
                }
            }
        }
        return instance;
    }

    public void setConfig(OtaConfig config) {
        this.config = config;
        // Update config in state machine as well
        this.otaStateMachine.setConfig(config);
    }

    public BleCommunicator getBleCommunicator() {
        return bleCommunicator;
    }

    public void setProgressListener(OtaProgressListener listener) {
        this.progressListener = listener;
        // Pass listener to state machine for direct updates
        this.otaStateMachine.setProgressListener(listener);
    }

    public void setConnectionStateListener(ConnectionStateListener listener) {
        this.connectionStateListener = listener;
    }

    public void setOtaDevice(BleDevice device) {
        this.targetDevice = device;
        addLog("设置OTA目标设备: " + (device != null ? device.getBleName() : "null"));

        // 随机MAC地址处理
        if (device != null && config.enableRandomMac) {
            String currentMac = device.getBleAddress();
            if (!historicalMacAddresses.contains(currentMac)) {
                historicalMacAddresses.add(currentMac);
                macAddressChangeCount++;
                addLog("检测到MAC地址变化: " + currentMac + " (第" + macAddressChangeCount + "次)");
            }
        }
    }

    // 前后台状态管理
    public void setAppForegroundState(boolean isInForeground) {
        if (!config.enableLifecycleManagement) return;

        this.isAppInForeground = isInForeground;
        addLog("应用状态变化: " + (isInForeground ? "前台" : "后台"));

        if (isInForeground) {
            adjustForegroundStrategy();
        } else {
            adjustBackgroundStrategy();
        }
    }

    private void adjustForegroundStrategy() {
        // 前台策略：恢复正常设置
        // Note: This logic should ideally be in OtaStateMachine or a dedicated RetryHandler
        // For now, keeping it here for simplicity during refactoring.
        config.maxRetryCount = OtaConstants.MAX_RETRY_COUNT;
        config.connectTimeout = OtaConstants.CONNECT_TIMEOUT;
        addLog("前台策略调整: 重试次数=" + config.maxRetryCount + ", 超时时间=" + config.connectTimeout);
    }

    private void adjustBackgroundStrategy() {
        // 后台策略：增加重试次数，延长超时时间
        config.maxRetryCount = OtaConstants.MAX_RETRY_COUNT * 2;
        config.connectTimeout = OtaConstants.CONNECT_TIMEOUT * 2;
        addLog("后台策略调整: 重试次数=" + config.maxRetryCount + ", 超时时间=" + config.connectTimeout);
    }

    public void setAppRestartState(boolean isRestarting) {
        this.isAppRestarting = isRestarting;
        if (isRestarting) {
            addLog("应用重启状态，保存OTA状态");
            // saveOtaState(); // Placeholder for persistence
        }
    }

    public boolean isOtaInProgress() {
        return otaStateMachine.isInProgress();
    }

    /**
     * 开始OTA升级
     * @param inputStream 固件文件输入流
     * @param creditCode 凭证码
     * @param macAddress MAC地址
     */
    public void startOta(BleDevice device, InputStream inputStream, String creditCode, String macAddress) {
        if (isOtaInProgress()) {
            addLog("OTA升级正在进行中");
            return;
        }

        this.targetDevice = device;
        this.creditCode = creditCode;
        this.macAddress = macAddress;
        this.retryState.reset();

        addLog("开始OTA升级: " + device.getBleName() + " (" + device.getBleAddress() + ")");

        try {
            // 获取文件物理大小（与Flutter端保持一致）
            long filePhysicalSize = 0;
            if (inputStream instanceof java.io.FileInputStream) {
                java.io.FileInputStream fis = (java.io.FileInputStream) inputStream;
                java.nio.channels.FileChannel channel = fis.getChannel();
                filePhysicalSize = channel.size();
                addLog("文件物理大小: " + filePhysicalSize + " 字节");
            } else {
                // 如果不是文件流，使用默认值
                addLog("无法获取文件物理大小，使用默认值");
                filePhysicalSize = 200 * 1024; // 默认200KB
            }
            
            // 一次性读取文件内容并解析
            List<String> fileLines = new ArrayList<>();
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    fileLines.add(line.trim());
                }
            }
            
            if (fileLines.isEmpty()) {
                notifyError(OtaConstants.ASK_STATE_UNKNOW, "OTA文件内容为空");
                return;
            }
            
            // 解析固件版本信息（与Flutter端保持一致）
            FirmwareParser.VersionInfo versionInfo = firmwareParser.parseVersionInfoFromLines(fileLines, filePhysicalSize);
            config.setFirmwareVersionInfo(versionInfo.romVersion, versionInfo.softwareVersion);
            
            addLog("固件版本信息 - ROM: " + versionInfo.romVersion + 
                   ", 软件版本: " + versionInfo.softwareVersion + 
                   ", 文件大小: " + versionInfo.fileSize + " KB");
            
            // 解析数据块
            otaBlocks = firmwareParser.parseFromLines(fileLines);
            if (otaBlocks.isEmpty()) {
                notifyError(OtaConstants.ASK_STATE_UNKNOW, "OTA文件数据块为空");
                return;
            }
            addLog("OTA文件解析完成，共" + otaBlocks.size() + "个数据块");
        } catch (IOException e) {
            notifyError(OtaConstants.ASK_STATE_UNKNOW, "OTA文件解析失败: " + e.getMessage());
            return;
        }

        // 创建BleRssiDevice包装器用于状态机
        BleRssiDevice rssiDevice;
        if (device instanceof BleRssiDevice) {
            rssiDevice = (BleRssiDevice) device;
        } else {
            rssiDevice = new BleRssiDevice(device.getBleAddress(), device.getBleName());
        }

        // 启动状态机
        otaStateMachine.startOta(rssiDevice, otaBlocks, creditCode, macAddress);
    }

    /**
     * 停止OTA升级
     */
    public void stopOta() {
        otaStateMachine.stopOta();
    }

    // BleCommunicator.CommunicationCallback implementation
    @Override
    public void onConnected(BleDevice device) {
        otaStateMachine.onConnected(device);
        if (connectionStateListener != null) {
            connectionStateListener.onConnectionStateChanged(device);
        }
    }

    @Override
    public void onDisconnected(BleDevice device) {
        otaStateMachine.onDisconnected(device);
        if (connectionStateListener != null) {
            connectionStateListener.onConnectionStateChanged(device);
        }
    }

    @Override
    public void onConnectFailed(BleDevice device, int errorCode) {
        // 添加调试日志
        addLog("OtaManager.onConnectFailed 被调用，设备: " + device.getBleName() + ", 错误码: " + errorCode);
        otaStateMachine.onConnectFailed(device, errorCode);
    }

    @Override
    public void onServicesDiscovered(BleDevice device) {
        addLog("OtaManager.onServicesDiscovered 被调用，设备: " + device.getBleName());
        otaStateMachine.onServicesDiscovered(device);
        addLog("OtaManager.onServicesDiscovered 已调用 otaStateMachine.onServicesDiscovered");
    }

    @Override
    public void onCharacteristicRead(BleDevice device, BluetoothGattCharacteristic characteristic) {
        addLog("OtaManager.onCharacteristicRead 被调用，特征值: " + characteristic.getUuid());
        otaStateMachine.onCharacteristicRead(device, characteristic);
        addLog("OtaManager.onCharacteristicRead 已调用 otaStateMachine.onCharacteristicRead");
    }

    @Override
    public void onCharacteristicWrite(BleDevice device, BluetoothGattCharacteristic characteristic) {
        otaStateMachine.onCharacteristicWrite(device, characteristic);
    }

    @Override
    public void onWriteFailed(BleDevice device, int errorCode) {
        addLog("写入失败，错误码: " + errorCode);
        
        // 转发给状态机处理
        otaStateMachine.onWriteFailed(device, errorCode);
        
        // 根据错误码提供具体的错误信息
        if (errorCode == 133) {
            // 133错误是正常的设备重启，不应该作为错误处理
            addLog("升级命令已发送，设备正在重启进入Boot模式...");
            // 不调用notifyError，让OtaStateMachine正常处理重启流程
            return;
        }
        
        String errorMessage = "写入失败";
        switch (errorCode) {
            case 8: // GATT_INSUFFICIENT_AUTHENTICATION
                errorMessage = "认证不足(8): 设备要求更高级别的认证";
                break;
            case 15: // GATT_INSUFFICIENT_ENCRYPTION
                errorMessage = "加密不足(15): 需要加密连接";
                break;
            default:
                errorMessage = "写入失败，错误码: " + errorCode;
                break;
        }
        
        // 通知错误
        notifyError(errorCode, errorMessage);
    }

    @Override
    public void onCharacteristicChanged(BleDevice device, BluetoothGattCharacteristic characteristic) {
        otaStateMachine.onCharacteristicChanged(device, characteristic);
    }

    @Override
    public void onDescriptorWriteSuccess(BleDevice device, android.bluetooth.BluetoothGattDescriptor descriptor) {
        otaStateMachine.onDescriptorWriteSuccess(device, descriptor);
    }

    @Override
    public void onMtuChanged(BleDevice device, int mtu, int status) {
        otaStateMachine.onMtuChanged(device, mtu, status);
    }

    @Override
    public void onReadRemoteRssi(BleDevice device, int rssi, int status) {
        otaStateMachine.onReadRemoteRssi(device, rssi, status);
    }

    // OtaStateMachine.StateMachineCallback implementation
    @Override
    public void onStateChanged(OtaState state) {
        if (progressListener != null) {
            progressListener.onStateChanged(state);
        }
    }

    @Override
    public void onProgressChanged(int progress, int total) {
        if (progressListener != null) {
            progressListener.onProgressChanged(progress, total);
        }
    }

    @Override
    public void onError(int errorCode, String errorMessage) {
        if (progressListener != null) {
            progressListener.onError(errorCode, errorMessage);
        }
        // Clean up resources on error
        cleanup();
    }

    @Override
    public void onSuccess() {
        if (progressListener != null) {
            progressListener.onSuccess();
        }
        // Clean up resources on success
        cleanup();
    }

    @Override
    public void onLog(String message) {
        // 添加调试日志确保能看到方法被调用
        BleLog.d(TAG, "OtaManager.onLog 被调用: " + message);
        
        if (progressListener != null) {
            BleLog.d(TAG, "progressListener 不为 null，转发日志");
            progressListener.onLog(message);
        } else {
            BleLog.w(TAG, "progressListener 为 null，无法转发日志");
        }
    }

    @Override
    public void onVersionInfo(String deviceVersion, String romVersion, String targetVersion) {
        if (progressListener != null) {
            progressListener.onVersionInfo(deviceVersion, romVersion, targetVersion);
        }
    }

    @Override
    public void onProtocolDetected(ProtocolVersion version) {
        if (progressListener != null) {
            progressListener.onProtocolDetected(version);
        }
    }

    // Retry handlers (delegated from OtaStateMachine, but managed here for scheduling)
    @Override
    public void scheduleConnectRetry(Runnable retryAction) {
        addLog("*** scheduleConnectRetry 被调用 ***");
        addLog("当前重试次数: " + retryState.connectRetryCount + ", 最大重试次数: " + config.maxRetryCount);
        
        if (retryState.connectRetryCount < config.maxRetryCount) {
            long delay = (long) (OtaConstants.CONNECT_RETRY_DELAY * Math.pow(2, retryState.connectRetryCount));
            retryState.connectRetryCount++;
            addLog("连接重试 " + retryState.connectRetryCount + "/" + config.maxRetryCount + "，延迟 " + delay + "ms");
            scheduleTimeout((int) delay, retryAction);
        } else {
            addLog("*** 重试次数已达最大值，不再重试 ***");
        }
    }

    @Override
    public void scheduleVersionCheckRetry(Runnable retryAction) {
        if (retryState.versionCheckRetryCount < config.versionCheckRetry) {
            long delay = (long) (OtaConstants.VERSION_CHECK_RETRY_DELAY * Math.pow(2, retryState.versionCheckRetryCount));
            retryState.versionCheckRetryCount++;
            addLog("版本检查重试 " + retryState.versionCheckRetryCount + "/" + config.versionCheckRetry + "，延迟 " + delay + "ms");
            scheduleTimeout((int) delay, retryAction);
        }
    }

    @Override
    public void scheduleCredentialCheckRetry(Runnable retryAction) {
        if (retryState.credentialCheckRetryCount < config.credentialCheckRetry) {
            long delay = (long) (OtaConstants.CREDENTIAL_CHECK_RETRY_DELAY * Math.pow(2, retryState.credentialCheckRetryCount));
            retryState.credentialCheckRetryCount++;
            addLog("凭证检查重试 " + retryState.credentialCheckRetryCount + "/" + config.credentialCheckRetry + "，延迟 " + delay + "ms");
            scheduleTimeout((int) delay, retryAction);
        }
    }

    @Override
    public void scheduleDataTransferRetry(Runnable retryAction) {
        if (retryState.dataTransferRetryCount < config.dataTransferRetry) {
            long delay = (long) (OtaConstants.DATA_TRANSFER_RETRY_DELAY * Math.pow(2, retryState.dataTransferRetryCount));
            retryState.dataTransferRetryCount++;
            addLog("数据传输重试 " + retryState.dataTransferRetryCount + "/" + config.dataTransferRetry + "，延迟 " + delay + "ms");
            scheduleTimeout((int) delay, retryAction);
        }
    }

    @Override
    public void scheduleVerificationRetry(Runnable retryAction) {
        if (retryState.verificationRetryCount < config.maxRetryCount) {
            long delay = (long) (OtaConstants.VERIFICATION_RETRY_DELAY * Math.pow(2, retryState.verificationRetryCount));
            retryState.verificationRetryCount++;
            addLog("验证重试 " + retryState.verificationRetryCount + "/" + config.maxRetryCount + "，延迟 " + delay + "ms");
            scheduleTimeout((int) delay, retryAction);
        }
    }

    @Override
    public void scheduleNextBlock(Runnable nextBlockAction) {
        scheduleTimeout(config.blockDelay, nextBlockAction);
    }

    /**
     * 调度超时任务
     */
    private void scheduleTimeout(int timeoutMs, Runnable timeoutAction) {
        cancelTimeout();
        timeoutTask = executorService.schedule(timeoutAction, timeoutMs, TimeUnit.MILLISECONDS);
    }

    /**
     * 取消超时任务
     */
    private void cancelTimeout() {
        if (timeoutTask != null && !timeoutTask.isCancelled()) {
            timeoutTask.cancel(true);
            timeoutTask = null;
        }
    }

    /**
     * 清理资源
     */
    private void cleanup() {
        otaBlocks.clear();
        retryState.reset();

        // Disconnect any active BLE connections
        if (targetDevice != null) {
            bleCommunicator.disconnect(targetDevice);
        }
        // phase2Device will be handled by OtaStateMachine if needed

        addLog("资源清理完成");
    }

    /**
     * 通知错误 (由OtaStateMachine调用，或OtaManager自身调用)
     */
    private void notifyError(int errorCode, String errorMessage) {
        if (progressListener != null) {
            progressListener.onError(errorCode, errorMessage);
        }
        // Clean up resources on error
        cleanup();
    }

    /**
     * 添加日志
     */
    private void addLog(String message) {
        // OtaManager no longer holds current state directly, get from state machine
        String currentStateDesc = otaStateMachine != null ? otaStateMachine.getCurrentState().getDescription() : "";
        String logMessage = "[" + currentStateDesc + "] " + message;
        log(logMessage);

        // 增强保护：避免回调到已销毁的Activity实例
        if (progressListener != null) {
            try {
                progressListener.onLog(logMessage);
            } catch (Exception e) {
                // 如果回调失败（比如Activity已销毁），清除监听器并只记录到控制台
                logError("Listener callback failed", e);
                progressListener = null;
            }
        }
    }

    private void log(String logMessage) {
        BleLog.d(TAG, logMessage);
    }

    private void logError(String errorMessage, Exception e) {
        BleLog.e(TAG, errorMessage + ": " + e.getMessage());
    }

    /**
     * 释放资源
     */
    public void release() {
        stopOta();

        if (executorService != null && !executorService.isShutdown()) {
            executorService.shutdown();
        }

        progressListener = null;
        addLog("OtaManager已释放");
    }

    // Getter方法
    public OtaState getCurrentState() {
        return otaStateMachine.getCurrentState();
    }

    public int getCurrentProgress() {
        return otaStateMachine.getCurrentProgress();
    }

    public String getDeviceVersion() {
        return otaStateMachine.getDeviceVersion();
    }

    public String getDeviceRomVersion() {
        return otaStateMachine.getDeviceRomVersion();
    }

    public String getTargetVersion() {
        return otaStateMachine.getTargetVersion();
    }

    public ProtocolVersion getDetectedVersion() {
        return otaStateMachine.getDetectedVersion();
    }

    public int getProgress() {
        return otaStateMachine.getCurrentProgress();
    }

    public RetryState getRetryState() {
        return retryState;
    }

    public List<String> getHistoricalMacAddresses() {
        return new ArrayList<>(historicalMacAddresses);
    }

    public int getMacAddressChangeCount() {
        return macAddressChangeCount;
    }

    public List<OtaBlock> getOtaBlocks() {
        return otaBlocks;
    }

    public static String getErrorDescription(int errorCode) {
        return OtaConstants.getErrorDescription(errorCode);
    }
}